package com.hahaliu.hahaliu.im;

import com.hahaliu.hahaliu.im.handler.TokenValidationHandler;
import com.hahaliu.hahaliu.im.handler.WebSocketHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.stream.ChunkedWriteHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

@Component
@Slf4j
public class IMServer {

    // 存储每个用户的全部连接
    public static final Map<Integer, Set<Channel>> userChannel = new ConcurrentHashMap<>();

    public void start() throws InterruptedException {

        // 主从结构
        EventLoopGroup boss = new NioEventLoopGroup();
        EventLoopGroup worker = new NioEventLoopGroup();

        try {
            // 绑定监听端口
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.group(boss, worker)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            ChannelPipeline pipeline = socketChannel.pipeline(); // 处理流

                            // 添加 Http 编码解码器
                            pipeline.addLast(new HttpServerCodec())
                                    // 添加处理大数据的组件
                                    .addLast(new ChunkedWriteHandler())
                                    // 对 Http 消息做聚合操作方便处理，产生 FullHttpRequest 和 FullHttpResponse
                                    .addLast(new HttpObjectAggregator(1024 * 64))
                                    // Token 校验
                                    .addLast(new TokenValidationHandler())
                                    // 添加 WebSocket 支持
                                    .addLast(new WebSocketServerProtocolHandler("/im"))
                                    // WebSocket 处理逻辑
                                    .addLast(new WebSocketHandler());

                            log.info("WebSocket handlers initialized successfully.");
                        }
                    });

            // 绑定端口并启动服务
            ChannelFuture future = bootstrap.bind(7071).sync();
            log.info("IM Server started successfully on port 7071.");

            // 等待服务关闭
            future.channel().closeFuture().sync();

        } catch (InterruptedException e) {
            log.error("Error while starting IM server: ", e);
            throw e;
        } finally {
            // 优雅地关闭 Netty 服务器的两个线程池（即事件循环组）
            // 确保这些线程池在关闭时能够正确地处理正在进行的任务，避免丢失数据或留下未处理的连接
            boss.shutdownGracefully();
            worker.shutdownGracefully();
        }
    }
}
